﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Persons.Interfaces;
using Persons.DS;
using Persons.Classes;
using Persons.DataStore;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;

namespace Server
{
    /// <summary>
    /// Класс сервера
    /// </summary>
    public class Server
    {
        TcpListener Listener;
        int Port = 8001;
        string IP = "127.0.0.1";
        public static IDS ds;
        
        /// <summary>
        /// Запуск сервера с указанным наследником интерфейса фабрики
        /// </summary>
        /// <param name="_ds">Наследник фабрики</param>
        public Server(IDS _ds)
        {
            //Persona per = new Persona(1, "gh dfg456jk", "jkl", 987, null);
            //string xml = per.MakeXMLStrFromPersona();
            //per = Persona.GetPersonaFromXMLStr(xml);
            Listener = new TcpListener(IPAddress.Parse(IP), Port);
            Listener.Start();
            ds = _ds;
            while (true)
            {
                TcpClient input = Listener.AcceptTcpClient();
                Console.WriteLine("Get new client");
                string data = null;
                byte[] bytes = new byte[input.Available];
                int BytesRes;
                //принимаем команду+персону
                while ((BytesRes = input.GetStream().Read(bytes, 0, bytes.Length)) != 0)
                {
                    data += Encoding.Default.GetString(bytes, 0, BytesRes);
                }
                //int BytesRes = input.GetStream().Read(bytes, 0, bytes.Length);
                    
                //data += Encoding.ASCII.GetString(bytes, 0, BytesRes);
                Console.WriteLine("Input request: " + data);
                //input.GetStream().Write(Encoding.ASCII.GetBytes("OK"), 0, Encoding.ASCII.GetBytes("OK").Length);
                ////принимаем картинку, если есть
                //if (input.Available > 0)
                //{
                //    bytes = new byte[input.Available];
                //    input.GetStream().Read(bytes, 0, bytes.Length);
                //    Console.WriteLine("Image");
                //}
                //else
                //{
                //    bytes = null;
                //    Console.WriteLine("No Image");
                //}               
                //string[] split = data.Split(new Char[] { ';', '_' });
                string action = Persona.GetValue(data, "action");
                try
                {
                    List<Persona> list = DoOperation(action, data);
                    data = "";
                    if (list != null)
                    {
                        foreach (Persona p in list)
                        {
                            data += p.MakeXMLStrFromPersona();
                        }
                    }
                    Console.WriteLine("Output data:" + data);
                    input.GetStream().Write(Encoding.ASCII.GetBytes(data), 0, Encoding.ASCII.GetBytes(data).Length);
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                    //data = null;
                    //data = "error" + ";" + ex.Message.ToString();
                    //Console.WriteLine("Error:" + data);
                    //input.GetStream().Write(Encoding.ASCII.GetBytes(data), 0, Encoding.ASCII.GetBytes(data).Length);

                }
                
            }

        }
        /// <summary>
        /// Метод, выполняющий указанную операцию CRUD'а в соответствии с параметром "typeOfOperation"
        /// </summary>
        /// <param name="typeOfOperation">Тип операции CRUD (create, update, read, readid, delete)</param>
        /// <param name="data">Данные, необходимые для выполнения операции</param>
        /// <returns>Список персон (возможно значение null)</returns>
        public  List<Persona> DoOperation(string typeOfOperation, string data)
        {
            List<Persona> rez = null;
            switch (typeOfOperation)
            {
                case "insert":
                    {
                        ds.Create(Persona.GetPersonaFromXMLStr(data));
                        break;
                    }
                case "update":
                    {
                        ds.Update(Persona.GetPersonaFromXMLStr(data));
                        break;
                    }
                case "read":
                    {
                        rez = ds.Read();
                        break;
                    }
                case "readid":
                    {
                        rez = ds.Read(Convert.ToInt32(data));
                        break;
                    }
                case "delete":
                    {
                        ds.Delete(Convert.ToInt32(data));
                        break;
                    }
                default:
                    {
                        break;
                    }

            }
            return rez;
        }
        //private void NewClient(TcpClient input)
        //{
        //    data = null;
        //    bytes = new byte[input.ReceiveBufferSize];
        //    BytesRes = input.GetStream().Read(bytes, 0, bytes.Length);
        //    data += Encoding.ASCII.GetString(bytes, 0, BytesRes);
        //    Console.Write(data);
        //    split = data.Split(new Char[] { ';', '_' });
        //    try
        //    {
        //        List<Persona> list = DoOperation(split[0], split[1]);
        //        data = "";
        //        if (list != null)
        //        {
        //            foreach (Persona p in list)
        //            {
        //                data += Persona.MakeCSVStrFromPersona(p) + ";";
        //            }
        //        }
        //        Console.Write("input:" + data);
        //        input.GetStream().Write(Encoding.ASCII.GetBytes(data), 0, Encoding.ASCII.GetBytes(data).Length);
        //    }
        //    catch (Exception ex)
        //    {
        //        data = null;
        //        data = "error" + "_" + ex.Message.ToString();
        //        input.GetStream().Write(Encoding.ASCII.GetBytes(data), 0, Encoding.ASCII.GetBytes(data).Length);

        //    }
        //}
        /// <summary>
        /// Остановка сервера
        /// </summary>
        ~Server()
        {
            // Если "слушатель" был создан
            if (Listener != null)
            {
                // Остановим его
                Listener.Stop();
            }
        }
    }
}
